package compile;

import common.FileUtil;

import java.io.File;
import java.util.UUID;

/*
* 每一次编译+运行的过程称之为 compile.Task
* */
public class Task {
    // 提高代码的可维护性
    // 约定所有临时文件所在的目录
    private String WORK_DIR = null;
    // 约定代码的类名
    private String CLASS = null;
    // 约定要编译的代码文件名
    private String CODE = null;
    // 约定存放编译错误的文件名
    private String COMPILE_ERROR = null;
    // 约定存放运行时标准输出的文件名
    private String STDOUT = null;
    // 约定存放运行时标准错误文件名
    private String STDERR = null;

    public Task(){
        WORK_DIR = "./tmp/"+ UUID.randomUUID()+"/";
        CLASS = "Solution";
        CODE = WORK_DIR +"Solution.java";
        COMPILE_ERROR = WORK_DIR +"compileError.txt";
        STDOUT = WORK_DIR +"stdout.txt";
        STDERR = WORK_DIR +"stderr.txt";
    }

    /*
    * 这个Task提供的核心方法就叫做 compileAndRun 译为编译加运行
    * 参数: 要编译运行的源代码
    * 返回值: 表示编译运行的结果,编译出错/运行出错/正常通过...
    * */
    public Answer compileAndRun(Question question){
        Answer answer = new Answer();
        File workDir = new File(WORK_DIR);
        if(!workDir.exists()){
            workDir.mkdirs();
        }
        // 第一步: 生成.java文件 把question中的code写入一个Solution.java文件中
        FileUtil.writeFile(CODE,question.getCode());
        // 第二步: 创建子进程,调用javac进行编译 编译需要一个.java文件 compileError.txt
        String compileCmd = String.format("javac -encoding utf8 %s -d %s",CODE,WORK_DIR);
        CommandUtil.run(compileCmd, null, COMPILE_ERROR);
        if(!FileUtil.readFile(COMPILE_ERROR).equals("")){
            // 编译出错,返回answer 设置错误码为 1
            System.out.println("编译出错!");
            answer.setError(1);
            answer.setReason(COMPILE_ERROR);
            return answer;
        }
        // 第三步: 创建子进程,调用java命令并执行 将运行结果写入stdout.txt和stderr.txt
        String runCmd = String.format("java -classpath %s %s",WORK_DIR,CLASS);
        System.out.println(runCmd);
        CommandUtil.run(runCmd, STDOUT, STDERR);
        if(!FileUtil.readFile(STDERR).equals("")){
            // 运行出错,返回answer 设置错误码为 2
            System.out.println("运行出错!");
            answer.setError(2);
            answer.setStderr(STDERR);
            return answer;
        }
        // 第四步: 父进程获取到刚才编译运行的结果,封装到Answer对象中 从stdout.txt和stderr.txt 取内容
        answer.setError(0);
        answer.setStdout(FileUtil.readFile(STDOUT));
        return answer;
    }

    public static void main(String[] args) {
        Task task = new Task();
        Question question = new Question();
        question.setCode("public class Solution {\n" +
                "    public static void main(String[] args) {\n" +
                "        System.out.println(\"hello world\");\n" +
                "    }\n" +
                "}\n");
        Answer answer = task.compileAndRun(question);
        System.out.println(answer);
    }
}


